home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 #1 / Ham Radio 2000.iso / ham2000 / tcp_ip / tnos / tnos100s / iface.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-11-19  |  16.0 KB  |  698 lines

  1. /* IP interface control and configuration routines
  2.  * Copyright 1991 Phil Karn, KA9Q
  3.  *
  4.  * Mods by PA0GRI 
  5.  */
  6. #include <stdio.h>
  7. #include "global.h"
  8. #include "config.h"
  9. #include "mbuf.h"
  10. #include "proc.h"
  11. #include "iface.h"
  12. #include "ip.h"
  13. #include "netuser.h"
  14. #include "ax25.h"
  15. #include "enet.h"
  16. #include "pktdrvr.h"
  17. #include "cmdparse.h"
  18. #include "commands.h"
  19. #include "nr4.h"
  20.  
  21. #ifdef NETROM
  22. extern struct iface *Nr_iface;
  23. #endif
  24.  
  25. static void showiface __ARGS((struct iface *ifp));
  26. static int mask2width __ARGS((int32 mask));
  27. static int ifipaddr __ARGS((int argc,char *argv[],void *p));
  28. static int ifipcall __ARGS((int argc,char *argv[],void *p));
  29. static int iflinkadr __ARGS((int argc,char *argv[],void *p));
  30. static int ifbroad __ARGS((int argc,char *argv[],void *p));
  31. static int ifnetmsk __ARGS((int argc,char *argv[],void *p));
  32. static int ifrxbuf __ARGS((int argc,char *argv[],void *p));
  33. static int ifmtu __ARGS((int argc,char *argv[],void *p));
  34. static int ifforw __ARGS((int argc,char *argv[],void *p));
  35. static int ifencap __ARGS((int argc,char *argv[],void *p));
  36. static int ifdescr __ARGS((int argc,char *argv[],void *p));
  37. static int ifpaclen __ARGS((int argc,char *argv[],void *p));
  38. void dohelper __ARGS((char *title,struct cmds *cmdp, char *stopstr));
  39.  
  40. /* Interface list header */
  41. struct iface *Ifaces = &Loopback;
  42.  
  43. /* Loopback pseudo-interface */
  44. struct iface Loopback = {
  45. #ifdef ENCAP
  46.     &Encap,     /* Link to next entry */
  47. #else
  48.     NULLIF,
  49. #endif
  50.     "loopback", /* name     */
  51.     NULLCHAR,   /* description */
  52.     0x7f000001L,    /* addr        127.0.0.1 */
  53.     0xffffffffL,    /* broadcast    255.255.255.255 */
  54.     0xffffffffL,    /* netmask    255.255.255.255 */
  55.     MAXINT16,    /* mtu        No limit */
  56.     0,          /* AX.25 paclen, if applicable */
  57.     0,      /* flags    */
  58.     0,      /* quality  */
  59.     0,        /* trace    */
  60.     NULLCHAR,    /* trfile    */
  61.     NULLFILE,    /* trfp        */
  62.     NULLIF,        /* forw        */
  63.     NULLPROC,    /* rxproc    */
  64.     NULLPROC,    /* txproc    */
  65.     NULLPROC,    /* supv        */
  66.     0,        /* dev        */
  67.     NULL,        /* (*ioctl)    */
  68.     NULLFP,        /* (*iostatus)    */
  69.     NULLFP,        /* (*stop)    */
  70.     NULLCHAR,    /* hwaddr    */
  71.     NULLCHAR,    /* ipcall    */
  72.     NULL,        /* extension    */
  73.     CL_NONE,    /* type        */
  74.     0,        /* xdev        */
  75.     0,        /* port        */
  76.     &Iftypes[0],    /* iftype    */
  77.     NULLFP,        /* (*send)    */
  78.     NULLFP,        /* (*output)    */
  79.     NULLFP,        /* (*raw)    */
  80.     NULLVFP,    /* (*show)    */
  81.     NULLFP,        /* (*discard)    */
  82.     NULLFP,        /* (*echo)    */
  83.     0,        /* ipsndcnt    */
  84.     0,        /* rawsndcnt    */
  85.     0,        /* iprecvcnt    */
  86.     0,        /* rawrcvcnt    */
  87.     0,        /* lastsent    */
  88.     0,        /* lastrecv    */
  89. };
  90.  
  91. #ifdef ENCAP
  92. /* Encapsulation pseudo-interface */
  93. struct iface Encap = {
  94.     NULLIF,
  95.     "encap",    /* name        */
  96.     NULLCHAR,   /* description */
  97.     INADDR_ANY,    /* addr        0.0.0.0 */
  98.     0xffffffffL,    /* broadcast    255.255.255.255 */
  99.     0xffffffffL,    /* netmask    255.255.255.255 */
  100.     MAXINT16,    /* mtu        No limit */
  101.     0,          /* AX.25 paclen, if applicable */
  102.     0,      /* flags    */
  103.     0,      /* quality  */
  104.     0,        /* trace    */
  105.     NULLCHAR,    /* trfile    */
  106.     NULLFILE,    /* trfp        */
  107.     NULLIF,        /* forw        */
  108.     NULLPROC,    /* rxproc    */
  109.     NULLPROC,    /* txproc    */
  110.     NULLPROC,    /* supv        */
  111.     0,        /* dev        */
  112.     NULL,        /* (*ioctl)    */
  113.     NULLFP,        /* (*iostatus)    */
  114.     NULLFP,        /* (*stop)    */
  115.     NULLCHAR,    /* hwaddr    */
  116.     NULLCHAR,    /* ipcall    */
  117.     NULL,        /* extension    */
  118.     CL_NONE,    /* type        */
  119.     0,        /* xdev        */
  120.     0,        /* port        */
  121.     &Iftypes[0],    /* iftype    */
  122.     ip_encap,    /* (*send)    */
  123.     NULLFP,        /* (*output)    */
  124.     NULLFP,        /* (*raw)    */
  125.     NULLVFP,    /* (*show)    */
  126.     NULLFP,        /* (*discard)    */
  127.     NULLFP,        /* (*echo)    */
  128.     0,        /* ipsndcnt    */
  129.     0,        /* rawsndcnt    */
  130.     0,        /* iprecvcnt    */
  131.     0,        /* rawrcvcnt    */
  132.     0,        /* lastsent    */
  133.     0,        /* lastrecv    */
  134. };
  135. #endif /*ENCAP*/
  136.  
  137. char Noipaddr[] = "IP address field missing, and ip address not set\n";
  138.  
  139. struct cmds DFAR Ifcmds[] = {
  140.     "broadcast",        ifbroad,    0,    2,    NULLCHAR,
  141.     "description",      ifdescr,    0,  0,  NULLCHAR,
  142.     "encapsulation",    ifencap,    0,    2,    NULLCHAR,
  143.     "forward",        ifforw,        0,    2,    NULLCHAR,
  144.     "ipaddress",        ifipaddr,    0,    2,    NULLCHAR,
  145.     "ipcall",        ifipcall,    0,    2,    NULLCHAR,
  146.     "linkaddress",        iflinkadr,    0,    2,    NULLCHAR,
  147.     "mtu",            ifmtu,        0,    2,    NULLCHAR,
  148.     "netmask",        ifnetmsk,    0,    2,    NULLCHAR,
  149. #ifdef AX25
  150.     "paclen",       ifpaclen,   0,  2,  NULLCHAR,
  151. #endif
  152.     "rxbuf",        ifrxbuf,    0,  2,  NULLCHAR,
  153.     NULLCHAR,
  154. };
  155.  
  156. /* Set interface parameters */
  157. int
  158. doifconfig(argc,argv,p)
  159. int argc;
  160. char *argv[];
  161. void *p;
  162. {
  163.     struct iface *ifp;
  164.     int i;
  165.  
  166.     if(argc < 2){
  167.         for(ifp = Ifaces;ifp != NULLIF;ifp = ifp->next)
  168.             showiface(ifp);
  169.         return 0;
  170.     }
  171.     if((ifp = if_lookup(argv[1])) == NULLIF){
  172.         tprintf(Badinterface,argv[1]);
  173.         return 1;
  174.     }
  175.     if(argc == 2){
  176.         showiface(ifp);
  177.         if ( ifp->show != NULLVFP ) {
  178.             (*ifp->show)(ifp);
  179.         }
  180.         return 0;
  181.     }
  182.     if(argc == 3){
  183.         dohelper ("valid subcommands:\n", Ifcmds, NULLCHAR);
  184.         return 1;
  185.     }
  186.     for(i=2;i<argc-1;i+=2)
  187.         subcmd(Ifcmds,3,&argv[i-1],ifp);
  188.  
  189.     return 0;
  190. }
  191.  
  192. /* Set interface IP address */
  193. static int
  194. ifipaddr(argc,argv,p)
  195. int argc;
  196. char *argv[];
  197. void *p;
  198. {
  199.     struct iface *ifp = p;
  200.  
  201.     /* Do not allow loopback iface to be changed ! - WG7J */
  202.     if(ifp == &Loopback) {
  203.         tputs("Cannot change IP address !\n");
  204.         return 0;
  205.     }
  206.     ifp->addr = resolve(argv[1]);
  207.     return 0;
  208. }
  209.  
  210.  
  211. /* Set IP call sign */
  212. static int
  213. ifipcall(argc,argv,p)
  214. int argc;
  215. char *argv[];
  216. void *p;
  217. {
  218.     struct iface *ifp = p;
  219.  
  220.     if(ifp->iftype == NULLIFT || ifp->iftype->scan == NULL){
  221.         tprintf("Can't set IP call\n");
  222.         return 1;
  223.     }
  224.     if(ifp->ipcall != NULLCHAR)
  225.         free(ifp->ipcall);
  226.     ifp->ipcall = mallocw(ifp->iftype->hwalen);
  227.     (*ifp->iftype->scan)(ifp->ipcall,argv[1]);
  228.     return 0;
  229. }
  230.  
  231. /* Set link (hardware) address */
  232. static int
  233. iflinkadr(argc,argv,p)
  234. int argc;
  235. char *argv[];
  236. void *p;
  237. {
  238.     struct iface *ifp = p;
  239.  
  240.     if(ifp->iftype == NULLIFT || ifp->iftype->scan == NULL){
  241.         tprintf("Can't set link address\n");
  242.         return 1;
  243.     }
  244.     if(ifp->hwaddr != NULLCHAR)
  245.         free(ifp->hwaddr);
  246.     ifp->hwaddr = mallocw(ifp->iftype->hwalen);
  247.     (*ifp->iftype->scan)(ifp->hwaddr,argv[1]);
  248. #ifdef MAILBOX
  249. #ifdef NETROM
  250.     if(ifp == Nr_iface) /*the netrom call just got changed! - WG7J*/
  251.         setmbnrid();
  252. #endif
  253. #endif
  254.     return 0;
  255. }
  256.  
  257. /* Set interface broadcast address. This is actually done
  258.  * by installing a private entry in the routing table.
  259.  */
  260. static int
  261. ifbroad(argc,argv,p)
  262. int argc;
  263. char *argv[];
  264. void *p;
  265. {
  266.     struct iface *ifp = p;
  267.     struct route *rp;
  268.  
  269.     rp = rt_blookup(ifp->broadcast,32);
  270.     if(rp != NULLROUTE && rp->iface == ifp)
  271.         rt_drop(ifp->broadcast,32);
  272.     ifp->broadcast = resolve(argv[1]);
  273.     rt_add(ifp->broadcast,32,0L,ifp,1L,0L,1);
  274.     return 0;
  275. }
  276.  
  277. /* Set the network mask. This is actually done by installing
  278.  * a routing entry.
  279.  */
  280. static int
  281. ifnetmsk(argc,argv,p)
  282. int argc;
  283. char *argv[];
  284. void *p;
  285. {
  286.     struct iface *ifp = p;
  287.     struct route *rp;
  288.  
  289.     /* Remove old entry if it exists */
  290.     rp = rt_blookup(ifp->addr & ifp->netmask,mask2width(ifp->netmask));
  291.     if(rp != NULLROUTE)
  292.         rt_drop(rp->target,rp->bits);
  293.  
  294.     ifp->netmask = htol(argv[1]);
  295.     rt_add(ifp->addr,mask2width(ifp->netmask),0L,ifp,0L,0L,0);
  296.     return 0;
  297. }
  298.  
  299. /* Command to set interface encapsulation mode */
  300. static int
  301. ifencap(argc,argv,p)
  302. int argc;
  303. char *argv[];
  304. void *p;
  305. {
  306.     struct iface *ifp = p;
  307.  
  308.     if(setencap(ifp,argv[1]) != 0){
  309.         tprintf("Encapsulation mode '%s' unknown\n",argv[1]);
  310.         return 1;
  311.     }
  312.     return 0;
  313. }
  314. /* Function to set encapsulation mode */
  315. int
  316. setencap(ifp,mode)
  317. struct iface *ifp;
  318. char *mode;
  319. {
  320.     struct iftype *ift;
  321.  
  322.     for(ift = &Iftypes[0];ift->name != NULLCHAR;ift++)
  323.         if(strnicmp(ift->name,mode,strlen(mode)) == 0)
  324.             break;
  325.     if(ift->name == NULLCHAR){
  326.         return -1;
  327.     }
  328.     ifp->iftype = ift;
  329.     ifp->send = ift->send;
  330.     ifp->output = ift->output;
  331.     ifp->type = ift->type;
  332. #ifdef AX25
  333.     if(ift->type == CL_AX25)
  334.         ifp->paclen = Paclen; /* default to the 'ax25 paclen' value */
  335. #endif
  336.     return 0;
  337. }
  338. /* Set interface receive buffer size */
  339. static int
  340. ifrxbuf(argc,argv,p)
  341. int argc;
  342. char *argv[];
  343. void *p;
  344. {
  345.     return 0;    /* To be written */
  346. }
  347.  
  348. /* Set interface Maximum Transmission Unit */
  349. static int
  350. ifmtu(argc,argv,p)
  351. int argc;
  352. char *argv[];
  353. void *p;
  354. {
  355.     struct iface *ifp = p;
  356.  
  357.     ifp->mtu = atoi(argv[1]);
  358. #ifdef NETROM
  359.     /* Make sure NETROM mtu <= 236 ! - WG7J */
  360.     if(ifp == Nr_iface)
  361.         if(Nr_iface->mtu > NR4MAXINFO)
  362.             Nr_iface->mtu = NR4MAXINFO;
  363. #endif
  364.     return 0;
  365. }
  366.  
  367. #ifdef AX25
  368.  
  369. /* Set interface AX.25 Paclen, and adjust the NETROM mtu for the
  370.  * smallest paclen. - WG7J
  371.  */
  372. static int
  373. ifpaclen(argc,argv,p)
  374. int argc;
  375. char *argv[];
  376. void *p;
  377. {
  378.     struct iface *ifp = p;
  379. #ifdef NETROM
  380.     int tmp;
  381. #endif
  382.  
  383.     if(ifp->iftype->type == CL_AX25) {
  384.         ifp->paclen = atoi(argv[1]);
  385. #ifdef NETROM
  386.         if(ifp->flags & IS_NR_IFACE)
  387.             if((tmp=ifp->paclen - 20) < Nr_iface->mtu)
  388.                 Nr_iface->mtu = tmp;
  389. #endif
  390.     } else
  391.         tputs("Not ax.25 interface!\n");
  392.     return 0;
  393. }
  394. #endif
  395.  
  396. /* Set interface forwarding */
  397. static int
  398. ifforw(argc,argv,p)
  399. int argc;
  400. char *argv[];
  401. void *p;
  402. {
  403.     struct iface *ifp = p;
  404.  
  405.     ifp->forw = if_lookup(argv[1]);
  406.     if(ifp->forw == ifp)
  407.         ifp->forw = NULLIF;
  408.     return 0;
  409. }
  410.  
  411. /*give a little description for each interface - WG7J*/
  412. static int
  413. ifdescr(argc,argv,p)
  414. int argc;
  415. char *argv[];
  416. void *p;
  417. {
  418.     struct iface *ifp = p;
  419.  
  420. #ifdef NETROM
  421. #ifdef ENCAP
  422.     if((ifp == &Loopback) || (ifp == &Encap) || (ifp == Nr_iface))
  423. #else
  424.     if((ifp == &Loopback) || (ifp == Nr_iface))
  425. #endif /*ENCAP*/
  426. #else  /*NETROM*/
  427. #ifdef ENCAP
  428.     if((ifp == &Loopback) || (ifp == &Encap))
  429. #else
  430.     if(ifp == &Loopback)
  431. #endif /*ENCAP*/
  432. #endif /*NETROM*/
  433.         return 0;
  434.  
  435.     if(ifp->descr != NULLCHAR){
  436.         free(ifp->descr);
  437.         ifp->descr = NULLCHAR;        /* reset the pointer */
  438.     }
  439.     if(!strlen(argv[1]))
  440.         return 0;           /* clearing the buffer */
  441.  
  442.     ifp->descr = mallocw(strlen(argv[1])+5); /* allow for the EOL char etc */
  443.     strcpy(ifp->descr, argv[1]);
  444.     strcat(ifp->descr, "\n");         /* add the EOL char */
  445.  
  446.     return 0;
  447. }
  448.  
  449.  
  450.  
  451. /* Display the parameters for a specified interface */
  452. static void
  453. showiface(ifp)
  454. register struct iface *ifp;
  455. {
  456.     char tmp[25];
  457.  
  458.     tprintf("%-10s IP addr %s MTU %u Link encap ",ifp->name,
  459.      inet_ntoa(ifp->addr),(int)ifp->mtu);
  460.     if(ifp->iftype == NULLIFT){
  461.         tprintf("not set\n");
  462.     } else {
  463.         tprintf("%s\n",ifp->iftype->name);
  464.         if(ifp->iftype->format != NULL && ifp->hwaddr != NULLCHAR) {
  465.             tprintf("           Link addr %s",
  466.              (*ifp->iftype->format)(tmp,ifp->hwaddr));
  467.             if(ifp->iftype->type == CL_AX25)
  468.                 tprintf("   Paclen %d",(int)ifp->paclen);
  469.             if(ifp->ipcall != NULLCHAR)
  470.                 tprintf("   IP call %s", (*ifp->iftype->format)(tmp,ifp->ipcall));
  471.             tputc('\n');
  472.         }
  473.     }
  474.     tprintf("           flags %u trace 0x%x netmask 0x%08lx broadcast %s\n",
  475.         ifp->flags,ifp->trace,ifp->netmask,inet_ntoa(ifp->broadcast));
  476.     if(ifp->forw != NULLIF)
  477.         tprintf("           output forward to %s\n",ifp->forw->name);
  478.     tprintf("           sent: ip %lu tot %lu idle %s\n",
  479.      ifp->ipsndcnt,ifp->rawsndcnt,tformat(secclock() - ifp->lastsent));
  480.     tprintf("           recv: ip %lu tot %lu idle %s\n",
  481.      ifp->iprecvcnt,ifp->rawrecvcnt,tformat(secclock() - ifp->lastrecv));
  482.     if(ifp->descr != NULLCHAR)
  483.         tprintf("           descr: %s",ifp->descr);
  484.  
  485. }
  486.  
  487. /* Command to detach an interface */
  488. int
  489. dodetach(argc,argv,p)
  490. int argc;
  491. char *argv[];
  492. void *p;
  493. {
  494.     register struct iface *ifp;
  495.  
  496.     if((ifp = if_lookup(argv[1])) == NULLIF){
  497.         tprintf(Badinterface,argv[1]);
  498.         return 1;
  499.     }
  500.     if(if_detach(ifp) == -1)
  501.         tprintf("Can't detach loopback or encap interface\n");
  502.     return 0;
  503. }
  504. /* Detach a specified interface */
  505. int
  506. if_detach(ifp)
  507. register struct iface *ifp;
  508. {
  509.     struct iface *iftmp;
  510.     struct route *rp,*rptmp;
  511.     int i,j;
  512.  
  513. #ifdef ENCAP
  514.     if(ifp == &Loopback || ifp == &Encap)
  515. #else
  516.     if(ifp == &Loopback)
  517. #endif
  518.             return -1;
  519.  
  520.     /* Drop all routes that point to this interface */
  521.     if(R_default.iface == ifp)
  522.         rt_drop(0L,0);    /* Drop default route */
  523.  
  524.     for(i=0;i<HASHMOD;i++){
  525.         for(j=0;j<32;j++){
  526.             for(rp = Routes[j][i];rp != NULLROUTE;rp = rptmp){
  527.                 /* Save next pointer in case we delete this entry */
  528.                 rptmp = rp->next;
  529.                 if(rp->iface == ifp)
  530.                     rt_drop(rp->target,rp->bits);
  531.             }
  532.         }
  533.     }
  534.     /* Unforward any other interfaces forwarding to this one */
  535.     for(iftmp = Ifaces;iftmp != NULLIF;iftmp = iftmp->next){
  536.         if(iftmp->forw == ifp)
  537.             iftmp->forw = NULLIF;
  538.     }
  539.  
  540.     /* Call device shutdown routine, if any */
  541.     if(ifp->stop != NULLFP)
  542.         (*ifp->stop)(ifp);
  543.  
  544.     killproc(ifp->rxproc);
  545.     killproc(ifp->txproc);
  546.     killproc(ifp->supv);
  547.  
  548. #ifdef NETROM
  549.     /*make sure that the netrom interface is properly detached
  550.      *fixed 11/15/91, Johan. K. Reinalda, WG7J/PA3DIS
  551.      */
  552.     if(strcmp(ifp->name,"netrom") == 0) {
  553.         for(iftmp=Ifaces;iftmp;iftmp=iftmp->next)
  554.             iftmp->flags &= ~IS_NR_IFACE; /* this 'resets' active interfaces */
  555.         Nr_iface = NULLIF;
  556.     }
  557. #endif
  558.  
  559.     /* Free allocated memory associated with this interface */
  560.     if(ifp->name != NULLCHAR)
  561.         free(ifp->name);
  562.     if(ifp->hwaddr != NULLCHAR)
  563.         free(ifp->hwaddr);
  564.     if(ifp->ipcall != NULLCHAR)
  565.         free(ifp->ipcall);
  566.  
  567.     /* Remove from interface list */
  568.     if(ifp == Ifaces){
  569.         Ifaces = ifp->next;
  570.     } else {
  571.         /* Search for entry just before this one
  572.          * (necessary because list is only singly-linked.)
  573.          */
  574.         for(iftmp = Ifaces;iftmp != NULLIF ;iftmp = iftmp->next)
  575.             if(iftmp->next == ifp)
  576.                 break;
  577.         if(iftmp != NULLIF && iftmp->next == ifp)
  578.             iftmp->next = ifp->next;
  579.     }
  580.     /* Finally free the structure itself */
  581.     free((char *)ifp);
  582.     return 0;
  583. }
  584.  
  585. /* Given the ascii name of an interface, return a pointer to the structure,
  586.  * or NULLIF if it doesn't exist
  587.  */
  588. struct iface *
  589. if_lookup(name)
  590. char *name;
  591. {
  592.     register struct iface *ifp;
  593.  
  594.     for(ifp = Ifaces; ifp != NULLIF; ifp = ifp->next)
  595.         if(stricmp(ifp->name,name) == 0)
  596.             break;
  597.     return ifp;
  598. }
  599.  
  600. /* Return iface pointer if 'addr' belongs to one of our interfaces,
  601.  * NULLIF otherwise.
  602.  * This is used to tell if an incoming IP datagram is for us, or if it
  603.  * has to be routed.
  604.  */
  605. struct iface *
  606. ismyaddr(addr)
  607. int32 addr;
  608. {
  609.     register struct iface *ifp;
  610.  
  611.     for(ifp = Ifaces; ifp != NULLIF; ifp = ifp->next)
  612.         if(addr == ifp->addr)
  613.             break;
  614.     return ifp;
  615. }
  616.  
  617. /* Given a network mask, return the number of contiguous 1-bits starting
  618.  * from the most significant bit.
  619.  */
  620. static int
  621. mask2width(mask)
  622. int32 mask;
  623. {
  624.     int width,i;
  625.  
  626.     width = 0;
  627.     for(i = 31;i >= 0;i--){
  628.         if(!(mask & (1L << i)))
  629.             break;
  630.         width++;
  631.     }
  632.     return width;
  633. }
  634.  
  635. /* return buffer with name + comment */
  636. char *
  637. if_name(ifp,comment)
  638. struct iface *ifp;
  639. char *comment;
  640. {
  641.     char *result = mallocw( strlen(ifp->name) + strlen(comment) + 1 );
  642.     strcpy( result, ifp->name );
  643.     return strcat( result, comment );
  644. }
  645.  
  646. /* Raw output routine that tosses all packets. Used by dialer, tip, etc */
  647. int
  648. bitbucket(ifp,bp)
  649. struct iface *ifp;
  650. struct mbuf *bp;
  651. {
  652.     free_p(bp);
  653.     return 0;
  654. }
  655.  
  656. /* Set interface (or AX25) flags on 1 or all interfaces */
  657. int
  658. dosetflag(argc,argv,p,flagtoset,AX25only)
  659. int argc;
  660. char *argv[];
  661. void *p;
  662. int flagtoset, AX25only;
  663. {
  664. struct iface *ifp;
  665.  
  666.     if(argc < 2) {
  667.         for(ifp = Ifaces;ifp != NULLIF;ifp = ifp->next)
  668.             if(ifp->flags & flagtoset)
  669.         tprintf("%s\n",ifp->name);
  670.     } else {
  671.         if((argc == 3) && (strcmp(argv[1],"all") == 0)) {
  672.             for(ifp = Ifaces;ifp != NULLIF;ifp = ifp->next)
  673.                 if(!AX25only || ifp->type == CL_AX25) {
  674.                     if(strcmp(argv[2],"on") == 0)
  675.                         ifp->flags |= flagtoset;
  676.                     else if(strcmp(argv[2],"off") == 0)
  677.                         ifp->flags &= ~flagtoset;
  678.                     else {
  679.                         tprintf("Please use on or off.\n");
  680.                         return 0;
  681.                     }
  682.                 }
  683.             return 0;
  684.         } else if((ifp = if_lookup(argv[1])) == NULLIF){
  685.             tprintf(Badinterface,argv[1]);
  686.             return 1;
  687.         }
  688.         if(AX25only && ifp->type != CL_AX25) {
  689.             tprintf("not an AX.25 interface\n");
  690.             return -1;
  691.         }
  692.         ifp->flags ^= flagtoset;
  693.     }
  694.     return 0;
  695. }
  696.  
  697.  
  698.